/**
 * @file demo_parse_json_data.c
 * @author David Hu (hmd_hubei_cn@163.com)
 * @brief 使用CJSON库API从文件中读取json格式字符串并解析JSON数据
 * @version 0.1
 * @date 2022-12-24
 * 
 * Copyright (c) 2022 DAVID HU All rights reserved.
 * 
 * 编译方法: gcc demo_parse_json_data.c cJSON.c
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"

int main(int argc, char const *argv[]) {
  // 打开JSON文件获取JSON数据
  FILE* p_jsonfile = NULL;
  p_jsonfile = fopen("./test.json", "r");
  if (p_jsonfile == NULL) {
    printf("open file fail\n");
    return -1;
  }
  // --  获取JSON文件的文件大小
  fseek(p_jsonfile, 0, SEEK_END); // 文件流指针定位到文件结束位置
  int val_file_size = 0;
  val_file_size = ftell(p_jsonfile); // 获取当前位置的索引值
  printf("file size: %d\n", val_file_size);
  fseek(p_jsonfile, 0, SEEK_SET); // 文件流指针定位到文件开始位置

  // -- 申请内存存储JSON数据
  char* json_str = (char*)malloc(sizeof(char)*val_file_size+1);
  memset(json_str, 0, val_file_size + 1);

  // -- 读取文件中的JSON数据
  int ret = fread(json_str, sizeof(char), val_file_size, p_jsonfile);
  if (ret <= 0) {
    printf("read file fail.\n");
    free(json_str);
    fclose(p_jsonfile);
    return -1;
  }
  fclose(p_jsonfile);
  printf("readed data:\n");
  printf("%s\n", json_str);

  // 解析JSON数据
  cJSON* root = cJSON_Parse(json_str);
  if (root == NULL) {
    printf("Error before: [%s]\n", cJSON_GetErrorPtr());
    free(json_str);
    return -1;
  }

  cJSON* name = cJSON_GetObjectItem(root, "name");
  if (name == NULL) {
    printf("Error before: [%s]\n", cJSON_GetErrorPtr());
    free(json_str);
    return -1;
  } else {
    if (name->type == cJSON_String) {
      char* val_str = name->valuestring; // 此处未重新申请空间，只是已申请空间的地址值传递
      printf("name = %s\n", val_str);
    }
  }

  cJSON* age = cJSON_GetObjectItem(root, "age");
  if (age == NULL) {
    printf("Error before: [%s]\n", cJSON_GetErrorPtr());
    free(json_str);
    return -1;
  } else {
    if (age->type == cJSON_Number) {
      int val_int = age->valueint;
      printf("age = %d\n", val_int);
    }
  }

  cJSON* height = cJSON_GetObjectItem(root, "height");
  if (height == NULL) {
    printf("Error before: [%s]\n", cJSON_GetErrorPtr());
    free(json_str);
    return -1;
  } else {
    if (height->type == cJSON_Number) {
      int val_int = height->valueint;
      printf("height = %d\n", val_int);
    }
  }

  cJSON* weight = cJSON_GetObjectItem(root, "weight");
  if (weight == NULL) {
    printf("Error before: [%s]\n", cJSON_GetErrorPtr());
    free(json_str);
    return -1;
  } else {
    if (weight->type == cJSON_Number) {
      int val_int = weight->valueint;
      printf("weight = %d\n", val_int);
    }
  }

  cJSON* student = cJSON_GetObjectItem(root, "student");
  if (student == NULL) {
    printf("Error before: [%s]\n", cJSON_GetErrorPtr());
    free(json_str);
    return -1;
  } else {
    if (student->type == cJSON_False) {
      int val_bool = student->valueint;
      printf("student = %s\n", (val_bool ? "true" : "false"));
    }
  }

  cJSON* address = cJSON_GetObjectItem(root, "address");
  if (address == NULL) {
    printf("Error before: [%s]\n", cJSON_GetErrorPtr());
    free(json_str);
    return -1;
  } else {
    cJSON* address_country = cJSON_GetObjectItem(address, "country");
    if (address_country == NULL) {
      printf("Error before: [%s]\n", cJSON_GetErrorPtr());
      free(json_str);
      return -1;
    } else {
      if (address_country->type == cJSON_String) {
        char* val_str = address_country->valuestring;
        printf("address->country = %s\n", val_str);
      }
    }

    cJSON* address_code = cJSON_GetObjectItem(address, "code");
    if (address_code == NULL) {
      printf("Error before: [%s]\n", cJSON_GetErrorPtr());
      free(json_str);
      return -1;
    } else {
      if (address_code->type == cJSON_Number) {
        int  val_int = address_code->valueint;
        printf("address->code = %d\n", val_int);
      }
    }
  }

  cJSON* skill = cJSON_GetObjectItem(root, "skill");
  if (skill == NULL) {
    printf("Error before: [%s]\n", cJSON_GetErrorPtr());
    free(json_str);
    return -1;
  } else {
    int val_array_size = cJSON_GetArraySize(skill);
    printf("array item size is %d\n", val_array_size);
    printf("skill [json array string]:\n");
    for (int i = 0; i < val_array_size; i++) {
      cJSON* array_item = cJSON_GetArrayItem(skill, i);
      if (array_item == NULL) {
        printf("Error before: [%s]\n", cJSON_GetErrorPtr());
        free(json_str);
        return -1;
      } else {
        if (array_item->type == cJSON_String) {
          char* val_str = array_item->valuestring;
          printf("%s\n", val_str);
        }
      }
    }
  }

  // 释放内存资源占用
  cJSON_Delete(root);
  free(json_str);

  return 0;
}
